import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Description 自定义代码模板
 * @Author Ciaj.
 * @Date 2019/9/16 15:50
 * @Version 1.0
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class MyGen {
	/**
	 * 数据库连接
	 */
	String jdbcUrl = "jdbc:mysql:///ciaj_sys?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&serverTimezone=Asia/Shanghai";
	/**
	 * 数据库驱动
	 */
	String jdbcDriver = "com.mysql.cj.jdbc.Driver";
	/**
	 * 数据库用户名
	 */
	String jdbcUser = "root";
	/**
	 * 数据库密码
	 */
	String jdbcPwd = "ciaj";
	/**
	 * 生成项目地址
	 */
	String projectPath = "";
	/**
	 * 输出项目目录
	 */
	String outPut = "/src/test/java";
	/**
	 * 生成者
	 */
	String author = "ciaj.";
	/**
	 * xml输出目录
	 */
	String mapperXmlPath = "/src/test/resources/mybatis/";
	/**
	 * po父类
	 */
	String superEntityClass = "com.baomidou.mybatisplus.samples.generator.common.BaseEntity";

	/**
	 * po父类包含的字段,短号隔开
	 */
	String superEntityColumns = "id,create_by,create_time,update_by,update_time,del,last_modify,com_id,version";


	/**
	 * dao父类
	 */
	String superMapperClass = "com.baomidou.mybatisplus.core.mapper.BaseMapper";

	/**
	 * 服务父类
	 */
	String superServiceClass = "com.baomidou.mybatisplus.extension.service.IService";

	/**
	 * 服务父实现类
	 */
	String superServiceImplClass = "com.baomidou.mybatisplus.extension.service.impl.ServiceImpl";


	/**
	 * mvc父类
	 */
	String superControllerClass = "com.baomidou.mybatisplus.samples.generator.common.BaseController";

	/**
	 * 包父级
	 */
	String packageParent = "gen.ciaj";
	/**
	 * entity包
	 */
	String packageEntity = "entity.po";
	/**
	 * mapper包
	 */
	String packageMapper = "mapper";
	/**
	 * entity包
	 */
	String packageMapperXml = "mapper";
	/**
	 * service包
	 */
	String packageService = "service";
	/**
	 * ServiceImpl包
	 */
	String packageServiceImpl = "service.impl";
	/**
	 * controller包
	 */
	String packageController = "controller";
	String controllerOutPath;

	/**
	 * restController 注解
	 */
	Boolean restControllerStyle = false;

	/**
	 * 是否生成xml
	 */
	Boolean isMpperXml = false;

	/**
	 * 是否生成Mapper
	 */
	Boolean isMpper = true;

	/**
	 * 是否生成实体
	 */
	Boolean isEntity = true;

	/**
	 * 是否生成服务
	 */
	Boolean isService = true;

	/**
	 * 是否生成服务实现
	 */
	Boolean isServiceImpl = true;

	/**
	 * 是否生成MVC
	 */
	Boolean isMvc = true;

	/**
	 * 是否生成Html
	 */
	Boolean isHtml = false;

	/**
	 * 是否生成Html
	 */
	Boolean swagger2 = false;

	/**
	 * Html输出目录
	 */
	String htmlOutPutPath = "/src/test/resources/templates/html/";

	public void generateTablePrefix(String moduleName,String tablePrefix) {
		AutoGenerator mpg = new AutoGenerator();
		if (StringUtils.isEmpty(projectPath)) projectPath = System.getProperty("user.dir");
		// 全局配置
		GlobalConfig gc = new GlobalConfig();
		gc.setOutputDir(projectPath + outPut);
		gc.setAuthor(author);
		gc.setOpen(false);
		gc.setSwagger2(swagger2);
		//默认不覆盖，如果文件存在，将不会再生成，配置true就是覆盖
		gc.setFileOverride(true);
		//xml
		gc.setBaseResultMap(true);
		gc.setBaseColumnList(true);
		//
		mpg.setGlobalConfig(gc);

		// 数据源配置
		DataSourceConfig dsc = new DataSourceConfig();
		dsc.setUrl(jdbcUrl);
		dsc.setDriverName(jdbcDriver);
		dsc.setUsername(jdbcUser);
		dsc.setPassword(jdbcPwd);
		mpg.setDataSource(dsc);

		// 包配置
		PackageConfig pc = new PackageConfig();
		pc.setModuleName(moduleName);
		pc.setEntity(packageEntity);
		pc.setMapper(packageMapper);
		pc.setXml(packageMapperXml);
		pc.setService(packageService);
		pc.setServiceImpl(packageServiceImpl);
		pc.setController(packageController);
		pc.setParent(packageParent);
		mpg.setPackageInfo(pc);

		//生成策略配置
		StrategyConfig strategy = new StrategyConfig();
		//要生成的表名
		//strategy.setInclude(null);
		//设置表前缀会如匹配上会截取掉
		strategy.setTablePrefix(tablePrefix);

		//下划线转驼峰命名
		strategy.setNaming(NamingStrategy.underline_to_camel);
		strategy.setColumnNaming(NamingStrategy.underline_to_camel);

		//过滤po父包的字段
		strategy.setSuperEntityColumns(superEntityColumns.split(","));

		//entity 父包
		strategy.setSuperEntityClass(superEntityClass);

		//【实体】是否为lombok模型（默认 false）
		strategy.setEntityLombokModel(true);

		//是否生成实体时，生成字段注解
		strategy.setEntityTableFieldAnnotationEnable(true);

		//dao 父包
		strategy.setSuperMapperClass(superMapperClass);

		//service 父包
		strategy.setSuperServiceClass(superServiceClass);

		//serviceImpl 父包
		strategy.setSuperServiceImplClass(superServiceImplClass);

		//mvc 父包
		strategy.setSuperControllerClass(superControllerClass);
		strategy.setRestControllerStyle(restControllerStyle);

		//mvc mapping 驼峰转连字符 <code>@RequestMapping("/managerUserActionHistory")</code> -> <code>@RequestMapping("/manager-user-action-history")</code>
		strategy.setControllerMappingHyphenStyle(true);

		mpg.setStrategy(strategy);
		// 选择 freemarker 引擎需要指定如下加，注意 pom 依赖必须有！
		mpg.setTemplateEngine(new FreemarkerTemplateEngine());
		//配置
		mpg.setCfg(custCfg(mpg));
		//模板
		mpg.setTemplate(custTemplate(mpg));
		//生成
		mpg.execute();
	}


	public void generate(String moduleName, String... tableNamesInclude) {
		AutoGenerator mpg = new AutoGenerator();
		if (StringUtils.isEmpty(projectPath)) projectPath = System.getProperty("user.dir");
		// 全局配置
		GlobalConfig gc = new GlobalConfig();
		gc.setOutputDir(projectPath + outPut);
		gc.setAuthor(author);
		gc.setOpen(false);
		gc.setSwagger2(swagger2);
		//默认不覆盖，如果文件存在，将不会再生成，配置true就是覆盖
		gc.setFileOverride(true);
		//xml
		gc.setBaseResultMap(true);
		gc.setBaseColumnList(true);
		//
		mpg.setGlobalConfig(gc);

		// 数据源配置
		DataSourceConfig dsc = new DataSourceConfig();
		dsc.setUrl(jdbcUrl);
		dsc.setDriverName(jdbcDriver);
		dsc.setUsername(jdbcUser);
		dsc.setPassword(jdbcPwd);
		mpg.setDataSource(dsc);

		// 包配置
		PackageConfig pc = new PackageConfig();
		pc.setModuleName(moduleName);
		pc.setEntity(packageEntity);
		pc.setMapper(packageMapper);
		pc.setXml(packageMapperXml);
		pc.setService(packageService);
		pc.setServiceImpl(packageServiceImpl);
		pc.setController(packageController);
		pc.setParent(packageParent);
		mpg.setPackageInfo(pc);

		//生成策略配置
		StrategyConfig strategy = new StrategyConfig();
		//要生成的表名
		strategy.setInclude(tableNamesInclude);
		//设置表前缀会如匹配上会截取掉
//		strategy.setTablePrefix(tablePrefix);

		//下划线转驼峰命名
		strategy.setNaming(NamingStrategy.underline_to_camel);
		strategy.setColumnNaming(NamingStrategy.underline_to_camel);

		//过滤po父包的字段
		strategy.setSuperEntityColumns(superEntityColumns.split(","));

		//entity 父包
		strategy.setSuperEntityClass(superEntityClass);

		//【实体】是否为lombok模型（默认 false）
		strategy.setEntityLombokModel(true);

		//是否生成实体时，生成字段注解
		strategy.setEntityTableFieldAnnotationEnable(true);

		//dao 父包
		strategy.setSuperMapperClass(superMapperClass);

		//service 父包
		strategy.setSuperServiceClass(superServiceClass);

		//serviceImpl 父包
		strategy.setSuperServiceImplClass(superServiceImplClass);

		//mvc 父包
		strategy.setSuperControllerClass(superControllerClass);
		strategy.setRestControllerStyle(restControllerStyle);

		//mvc mapping 驼峰转连字符 <code>@RequestMapping("/managerUserActionHistory")</code> -> <code>@RequestMapping("/manager-user-action-history")</code>
		strategy.setControllerMappingHyphenStyle(true);

		mpg.setStrategy(strategy);
		// 选择 freemarker 引擎需要指定如下加，注意 pom 依赖必须有！
		mpg.setTemplateEngine(new FreemarkerTemplateEngine());
		//配置
		mpg.setCfg(custCfg(mpg));
		//模板
		mpg.setTemplate(custTemplate(mpg));
		//生成
		mpg.execute();
	}

	/**
	 * 自定义模板
	 *
	 * @param mpg
	 */
	private TemplateConfig custTemplate(AutoGenerator mpg) {
		//配置 自定义模板
		TemplateConfig t = new TemplateConfig().setXml(null);
		//
		if (this.isEntity) {
			t.setEntity("templates/gen/Po.java");
		} else {
			t.setEntity(null);
		}
		//
		if (this.isMpper) {
			t.setMapper("templates/gen/Mapper.java");
		} else {
			t.setMapper(null);
		}
		//
		if (this.isService) {
			t.setService("templates/gen/Service.java");
		} else {
			t.setService(null);
		}
		//
		if (this.isServiceImpl) {
			t.setServiceImpl("templates/gen/ServiceImpl.java");
		} else {
			t.setServiceImpl(null);
		}
		//
		if (this.isMvc && this.controllerOutPath==null) {
			t.setController("templates/gen/Mvc.java");
		} else {
			t.setController(null);
		}
		return t;
	}

	/**
	 * 自定义配置
	 *
	 * @param mpg
	 * @return
	 */
	private InjectionConfig custCfg(AutoGenerator mpg) {
		// 自定义配置
		InjectionConfig cfg = new InjectionConfig() {
			@Override
			public void initMap() {
			}
		};

		List<FileOutConfig> focList = new ArrayList<>();
		if (this.isMpperXml) {
			focList.add(new FileOutConfig("templates/gen/Mapper.xml.ftl") {
				@Override
				public String outputFile(TableInfo tableInfo) {
					return org.apache.commons.lang3.StringUtils.joinWith("", projectPath,
							mapperXmlPath, mpg.getPackageInfo().getModuleName(), "/", tableInfo.getEntityName()
							, "Mapper", StringPool.DOT_XML);
				}
			});
		}
		if (this.isMvc && this.controllerOutPath!=null) {
			focList.add(new FileOutConfig("templates/gen/Mvc.java.ftl") {
				@Override
				public String outputFile(TableInfo tableInfo) {
					return org.apache.commons.lang3.StringUtils.joinWith("",
							controllerOutPath,outPut,"/",mpg.getPackageInfo().getParent().replace("\\.","/"),"/", "/controller/", tableInfo.getEntityName()
							, "Controller", StringPool.DOT_JAVA);
				}
			});
		}
		//
		if (this.isHtml) {
			if (this.isMpperXml) {
				focList.add(new FileOutConfig("templates/gen/Html.html.ftl") {
					@Override
					public String outputFile(TableInfo tableInfo) {
						return org.apache.commons.lang3.StringUtils.joinWith("", projectPath, htmlOutPutPath, mpg.getPackageInfo().getModuleName(), "/", tableInfo.getEntityName(), ".html");
					}
				});
			}
		}
		cfg.setFileOutConfigList(focList);
		return cfg;
	}


}
